home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / modelers / chmsthtc / chmsthtc.lzh / Chemesthetics / Source / Source.LZH / palettereq.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-07  |  16.4 KB  |  563 lines

  1. /****************************************************************************
  2.  *                                        *
  3.  *                 Palette Requester                    *
  4.  *                                        *
  5.  *             (c) Copyright 1989 Jonathan Potter                     *
  6.  *                                        *
  7.  * This program is freely redistributable, although all rights to it remain *
  8.  * with the author. It may be used freely in any program as long as this    *
  9.  * notice remains intact, however, if you do this, please mention the        *
  10.  * author in the program. If you wish to use this in a commercial program   *
  11.  * of any kind, you must register with a $15 donation.                *
  12.  * Please send donations, bug reports, comments and suggestions to :        *
  13.  *                                        *
  14.  *                Jonathan Potter                 *
  15.  *                3 William Street                *
  16.  *                Clarence Park 5034                *
  17.  *                South Australia                 *
  18.  *                Australia                    *
  19.  *                                        *
  20.  *               Ph : (08) 2932788  home                          *
  21.  *                                        *
  22.  ****************************************************************************/
  23.  
  24. #include <exec/types.h>
  25. #include <exec/memory.h>
  26. #include <intuition/intuitionbase.h>
  27. #include <intuition/screens.h>
  28. #include <libraries/dosextens.h>
  29. #include <graphics/gfxbase.h>
  30. #ifdef __SASC
  31. #include <proto/exec.h>
  32. #include <proto/intuition.h>
  33. #include <proto/graphics.h>
  34. #endif
  35. #include "PaletteReq.h"
  36.  
  37. #define RED 32
  38. #define BLUE 33
  39. #define GREEN 34
  40. #define CRESET 35
  41. #define CCANCEL 36
  42. #define COK 37
  43. #define USER 38
  44. #define SPREAD 39
  45. #define COPY 40
  46. #define HUE 41
  47. #define SAT 42
  48. #define LUM 43
  49.  
  50. #define INITREG(n)     (GetRGB4(cvp->ColorMap,n))
  51. #define REDREG(n)      ((n>>8)&0xf)
  52. #define GREENREG(n)    ((n>>4)&0xf)
  53. #define BLUEREG(n)     (n&0xf)
  54.  
  55. static int redtable[32], greentable[32], bluetable[32];
  56. static char values[4];
  57.  
  58. static struct IntuiText
  59.     coktext={1,0,JAM1,41,1,NULL,(UBYTE *)"OKAY",NULL},
  60.     canceltext={1,0,JAM1,33,1,NULL,(UBYTE *)"CANCEL",NULL},
  61.     usertext={1,0,JAM1,0,1,NULL,(UBYTE *)"",NULL},
  62.     resettext={1,0,JAM1,37,1,NULL,(UBYTE *)"RESET",NULL},
  63.     spreadtext={1,0,JAM1,33,1,NULL,(UBYTE *)"SPREAD",NULL},
  64.     copytext={1,0,JAM1,41,1,NULL,(UBYTE *)"COPY",NULL},
  65.     RText={1,0,JAM1,-15,1,NULL,"R",NULL},
  66.     GText={1,0,JAM1,-15,1,NULL,"G",NULL},
  67.     BText={1,0,JAM1,-15,1,NULL,"B",NULL},
  68.     HText={1,0,JAM1,106,1,NULL,"H",NULL},
  69.     SText={1,0,JAM1,106,1,NULL,"S",NULL},
  70.     LText={1,0,JAM1,106,1,NULL,"L",NULL},
  71.     valstext={0,1,JAM2,0,0,NULL,values,NULL};
  72.  
  73. static short border1_xy[]={
  74.     0,0,115,0,115,10,0,10,0,0};
  75. static struct Border border1={
  76.     -1,-1,1,0,JAM1,5,border1_xy,NULL};
  77. static short border2_xy[]={
  78.     0,0,239,0,239,10,0,10,0,0};
  79. static struct Border border2={
  80.     -1,-1,1,0,JAM1,5,border2_xy,NULL};
  81.  
  82. static struct PropInfo
  83.     RProp={AUTOKNOB|FREEHORIZ,0,0,1<<12},
  84.     GProp={AUTOKNOB|FREEHORIZ,0,0,1<<12},
  85.     BProp={AUTOKNOB|FREEHORIZ,0,0,1<<12},
  86.     HProp={AUTOKNOB|FREEHORIZ,0,0,1<<12},
  87.     SProp={AUTOKNOB|FREEHORIZ,0,0,1<<12},
  88.     LProp={AUTOKNOB|FREEHORIZ,0,0,1<<12};
  89.  
  90. static struct Image RImage, GImage, BImage, HImage, SImage, LImage,
  91.     WCol={0,0,235,8,1,NULL,0,1,NULL};
  92.  
  93. static struct Gadget
  94.     cokgadget={
  95.         NULL,9,118,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  96.         (APTR)&border1,NULL,&coktext,NULL,NULL,COK,NULL},
  97.     cancelgadget={
  98.         &cokgadget,133,118,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  99.         (APTR)&border1,NULL,&canceltext,NULL,NULL,CCANCEL,NULL},
  100.     usergadget={
  101.         &cancelgadget,133,105,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  102.         (APTR)&border1,NULL,&usertext,NULL,NULL,USER,NULL},
  103.     resetgadget={
  104.         &usergadget,9,105,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  105.         (APTR)&border1,NULL,&resettext,NULL,NULL,CRESET,NULL},
  106.     spreadgadget={
  107.         &resetgadget,133,92,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  108.         (APTR)&border1,NULL,&spreadtext,NULL,NULL,SPREAD,NULL},
  109.     copygadget={
  110.         &spreadgadget,9,92,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  111.         (APTR)&border1,NULL,©text,NULL,NULL,COPY,NULL},
  112.     Lum={
  113.         ©gadget,132,79,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  114.         (APTR)&LImage,NULL,<ext,NULL,(APTR)&LProp,LUM,NULL},
  115.     Sat={
  116.         &Lum,132,67,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  117.         (APTR)&SImage,NULL,&SText,NULL,(APTR)&SProp,SAT,NULL},
  118.     Hue={
  119.         &Sat,132,55,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  120.         (APTR)&HImage,NULL,&HText,NULL,(APTR)&HProp,HUE,NULL},
  121.     Red={
  122.         &Hue,24,55,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  123.         (APTR)&RImage,NULL,&RText,NULL,(APTR)&RProp,RED,NULL},
  124.     Green={
  125.         &Red,24,67,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  126.         (APTR)&GImage,NULL,>ext,NULL,(APTR)&GProp,GREEN,NULL},
  127.     Blue={
  128.         &Green,24,79,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  129.         (APTR)&BImage,NULL,&BText,NULL,(APTR)&BProp,BLUE,NULL};
  130.  
  131. static struct NewWindow colwin={
  132.     40,23,255,131,0,1,CLOSEWINDOW|GADGETUP|GADGETDOWN|MOUSEBUTTONS|RAWKEY,
  133.     WINDOWDRAG|WINDOWCLOSE|ACTIVATE|SMART_REFRESH|RMBTRAP,
  134.     &Blue,NULL,"Palette",NULL,NULL,0,0,0,0,CUSTOMSCREEN};
  135.  
  136. static struct Window *PWindow;
  137. static struct IntuiMessage *PMsg;
  138. static struct ViewPort *cvp;
  139. extern struct IntuitionBase *IntuitionBase;
  140. extern struct GfxBase *GfxBase;
  141. static ULONG colb;
  142.  
  143. palette_request(win,winx,winy,hail,user,depth)
  144. struct Window *win;
  145. int winx, winy;
  146. char *hail;
  147. char *user;
  148. int depth;
  149. {
  150.     int col,reg,i,Class,Code,GadgetID,x,y,last,first,sw,sh;
  151.     if (!IntuitionBase) return(NO_INTUITION);
  152.     if (!GfxBase) return(NO_GRAPHICS);
  153.     if (!win) { colwin.Type=WBENCHSCREEN; sw=640; sh=200; }
  154.     else {
  155.         colwin.Screen=win->WScreen;
  156.         sw=win->WScreen->Width; sh=win->WScreen->Height;
  157.     }
  158.     if (hail) colwin.Title=hail;
  159.     if (user) {
  160.         if (strlen(user)>14) user[14]='\0';
  161.         usertext.IText=user;
  162.         usertext.LeftEdge=(115-(strlen(user)*8))/2;
  163.     }
  164.     else {
  165.         resetgadget.NextGadget=&cancelgadget;
  166.         resetgadget.Width=238;
  167.         resetgadget.GadgetRender=(APTR)&border2;
  168.         resettext.LeftEdge=99;
  169.     }
  170.     if (winx>-1) {
  171.         colwin.LeftEdge=winx;
  172.         if (winx+255>sw)
  173.             colwin.LeftEdge=sw-255;
  174.     }
  175.     if (winy>-1) {
  176.         colwin.TopEdge=winy;
  177.         if (winy+131>sh)
  178.             colwin.TopEdge=sh-131;
  179.     }
  180.     PWindow=(struct Window *) OpenWindow(&colwin);
  181.     if (!PWindow) return(OPENWINDOW_FAILED);
  182.     cvp=&(PWindow->WScreen->ViewPort);
  183.     if (!depth) depth=2;
  184.     if (depth<1) depth=1; if (depth>5) depth=5;
  185.     drawersquares(depth);
  186.  
  187.     InitTable(depth);
  188.     col=1; WCol.PlaneOnOff=col;
  189.     valstext.FrontPen=col^(power(2,depth)-1); valstext.BackPen=1;
  190.     DrawImage(PWindow->RPort,&WCol,10,45);
  191.     PosPots(depth,col);
  192.     PosHSLPots(depth,col);
  193.     FOREVER {
  194.         Wait(1<<PWindow->UserPort->mp_SigBit);
  195.         while (PMsg=(struct IntuiMessage *) GetMsg(PWindow->UserPort)) {
  196.             Class=PMsg->Class; Code=PMsg->Code;
  197.             if (Class==GADGETUP || Class==GADGETDOWN)
  198.                 GadgetID=((struct Gadget *) PMsg->IAddress)->GadgetID;
  199.             ReplyMsg((struct Message *) PMsg);
  200.             switch (Class) {
  201.                 case CLOSEWINDOW:
  202.                     for (reg=0;reg<(power(2,depth));reg++)
  203.                         SetRGB4(cvp,reg,redtable[reg],greentable[reg],bluetable[reg]);
  204.                     CloseWindow(PWindow);
  205.                     return(FALSE);
  206.                     break;
  207.                 case MOUSEBUTTONS:
  208.                     if (Code!=SELECTDOWN) break;
  209.                     x=PWindow->MouseX; y=PWindow->MouseY;
  210.                     if (x<12 || x>243 || y<15 || y>40) break;
  211.                     if (col==ReadPixel(PWindow->RPort,x,y)) break;
  212.                     col=ReadPixel(PWindow->RPort,x,y);
  213.                     WCol.PlaneOnOff=col;
  214.                     DrawImage(PWindow->RPort,&WCol,10,45);
  215.                     PosPots(depth,col);
  216.                     PosHSLPots(depth,col);
  217.                     break;
  218.                 case GADGETDOWN:
  219.                     switch (GadgetID) {
  220.                         case RED:
  221.                         case GREEN:
  222.                         case BLUE:
  223.                             SetCols(depth,col);
  224.                             while (!(PMsg=(struct IntuiMessage *) GetMsg(PWindow->UserPort)))
  225.                                 SetCols(depth,col);
  226.                             ReplyMsg((struct Message *) PMsg);
  227.                             SetCols(depth,col);
  228.                             break;
  229.                         case HUE:
  230.                         case SAT:
  231.                         case LUM:
  232.                             SetHSLCols(depth,col);
  233.                             while (!(PMsg=(struct IntuiMessage *) GetMsg(PWindow->UserPort)))
  234.                                 SetHSLCols(depth,col);
  235.                             ReplyMsg((struct Message *) PMsg);
  236.                             SetHSLCols(depth,col);
  237.                             break;
  238.  
  239.                     }
  240.                     break;
  241.                 case RAWKEY:
  242.                     if (Code!=0x45) break;
  243.                     GadgetID=CRESET; Class=GADGETUP;
  244.                 case GADGETUP:
  245.                     switch (GadgetID) {
  246.                         case CRESET:
  247.                             for (reg=0;reg<(power(2,depth));reg++) {
  248.                                 SetRGB4(cvp,reg,redtable[reg],greentable[reg],bluetable[reg]);
  249.                                 if (reg==col) {
  250.                                     PosPots(depth,col);
  251.                                     PosHSLPots(depth,col);
  252.                                 }
  253.                             }
  254.                             break;
  255.                         case USER:
  256.                             if (!user) break;
  257.                             CloseWindow(PWindow);
  258.                             return(5);
  259.                         case COK:
  260.                             CloseWindow(PWindow);
  261.                             return(TRUE);
  262.                         case CCANCEL:
  263.                             for (reg=0;reg<(power(2,depth));reg++)
  264.                                 SetRGB4(cvp,reg,redtable[reg],greentable[reg],bluetable[reg]);
  265.                             CloseWindow(PWindow);
  266.                             return(FALSE);
  267.                         case COPY:
  268.                             FOREVER {
  269.                                 Wait(1<<PWindow->UserPort->mp_SigBit);
  270.                                 if (PMsg=(struct IntuiMessage *) GetMsg(PWindow->UserPort)) {
  271.                                     Class=PMsg->Class; Code=PMsg->Code;
  272.                                     ReplyMsg((struct Message *) PMsg);
  273.                                     if (Class!=MOUSEBUTTONS && Code!=SELECTDOWN) continue;
  274.                                     x=PWindow->MouseX; y=PWindow->MouseY;
  275.                                     if (x<12 || x>243 || y<15 || y>40) continue;
  276.                                     GadgetID=ReadPixel(PWindow->RPort,x,y);
  277.                                     if (GadgetID>-1 && GadgetID<32) break;
  278.                                 }
  279.                             }
  280.                             colb=INITREG(col);
  281.                             SetRGB4(cvp,GadgetID,REDREG(colb),GREENREG(colb),BLUEREG(colb));
  282.                             col=GadgetID;
  283.                             WCol.PlaneOnOff=col;
  284.                             DrawImage(PWindow->RPort,&WCol,10,45);
  285.                             PosPots(depth,col);
  286.                             PosHSLPots(depth,col);
  287.                         case SPREAD:
  288.                             FOREVER {
  289.                                 Wait(1<<PWindow->UserPort->mp_SigBit);
  290.                                 if (PMsg=(struct IntuiMessage *) GetMsg(PWindow->UserPort)) {
  291.                                     Class=PMsg->Class; Code=PMsg->Code;
  292.                                     ReplyMsg((struct Message *) PMsg);
  293.                                     if (Class!=MOUSEBUTTONS && Code!=SELECTDOWN) continue;
  294.                                     x=PWindow->MouseX; y=PWindow->MouseY;
  295.                                     if (x<12 || x>243 || y<15 || y>40) continue;
  296.                                     GadgetID=ReadPixel(PWindow->RPort,x,y);
  297.                                     if (GadgetID>-1 && GadgetID<32) break;
  298.                                 }
  299.                             }
  300.                             first=col; last=GadgetID;
  301.                             if (first>last) {
  302.                                 i=first; first=last; last=i;
  303.                             }
  304.                             if (first>=last-1) break;
  305.                             dospread(first,last);
  306.                             col=GadgetID;
  307.                             WCol.PlaneOnOff=col;
  308.                             DrawImage(PWindow->RPort,&WCol,10,45);
  309.                             PosPots(depth,col);
  310.                             PosHSLPots(depth,col);
  311.                             break;
  312.                         default:
  313.                             break;
  314.                     }
  315.             }
  316.         }
  317.     }
  318. }
  319.  
  320. static PosPots(depth,col)
  321. int depth,col;
  322. {
  323.     ULONG hpr,hpg,hpb;
  324.     colb=INITREG(col);
  325.     hpr=REDREG(colb)*0x1111;
  326.     hpg=GREENREG(colb)*0x1111;
  327.     hpb=BLUEREG(colb)*0x1111;
  328.     if (RProp.HorizPot==hpr && GProp.HorizPot==hpg && BProp.HorizPot==hpb)
  329.         return(0);
  330.     NewModifyProp(&Red,PWindow,NULL,FREEHORIZ|AUTOKNOB,hpr,0,1<<12,0,1);
  331.     NewModifyProp(&Green,PWindow,NULL,FREEHORIZ|AUTOKNOB,hpg,0,1<<12,0,1);
  332.     NewModifyProp(&Blue,PWindow,NULL,FREEHORIZ|AUTOKNOB,hpb,0,1<<12,0,1);
  333.     ShowVals(depth,REDREG(colb),GREENREG(colb),BLUEREG(colb),col);
  334.     return(0);
  335. }
  336.  
  337. static PosHSLPots(depth,col)
  338. int depth, col;
  339. {
  340.     colb=INITREG(col);
  341.     RGBToHSL(colb,&HProp.HorizPot,&SProp.HorizPot,&LProp.HorizPot);
  342.     NewModifyProp(&Hue,PWindow,NULL,FREEHORIZ|AUTOKNOB,HProp.HorizPot,0,1<<12,0,1);
  343.     NewModifyProp(&Sat,PWindow,NULL,FREEHORIZ|AUTOKNOB,SProp.HorizPot,0,1<<12,0,1);
  344.     NewModifyProp(&Lum,PWindow,NULL,FREEHORIZ|AUTOKNOB,LProp.HorizPot,0,1<<12,0,1);
  345.     return(0);
  346. }
  347.  
  348. static SetHSLCols(depth,col)
  349. int depth,col;
  350. {
  351.     ULONG rgb, red, green, blue;
  352.     rgb=(ULONG) HSLToRGB(HProp.HorizPot,SProp.HorizPot,LProp.HorizPot);
  353.     red=rgb>>8; green=rgb>>4; blue=rgb;
  354.     SetRGB4(cvp,col,red,green,blue);
  355.     PosPots(depth,col);
  356.     return(0);
  357. }
  358.  
  359. static SetCols(depth,col)
  360. int depth;
  361. int col;
  362. {
  363.     USHORT re,gr,bl;
  364.     re=RProp.HorizPot/0x1111;
  365.     gr=GProp.HorizPot/0x1111;
  366.     bl=BProp.HorizPot/0x1111;
  367.     colb=INITREG(col);
  368.     if (re==REDREG(colb) && gr==GREENREG(colb) && bl==BLUEREG(colb)) return(0);
  369.     SetRGB4(cvp,col,re,gr,bl);
  370.     ShowVals(depth,re,gr,bl,col);
  371.     PosHSLPots(depth,col);
  372.     return(0);
  373. }
  374.  
  375. static InitTable(depth)
  376. int depth;
  377. {
  378.     int reg;
  379.     for (reg=0;reg<(power(2,depth));reg++) {
  380.         colb=INITREG(reg);
  381.         redtable[reg]=REDREG(colb);
  382.         greentable[reg]=GREENREG(colb);
  383.         bluetable[reg]=BLUEREG(colb);
  384.     }
  385.     return(0);
  386. }
  387.  
  388. static ShowVals(depth,re,gr,bl,col)
  389. int depth,re,gr,bl,col;
  390. {
  391.     values[0]=dostr(re);
  392.     values[1]=dostr(gr);
  393.     values[2]=dostr(bl);
  394.     values[3]='\0';
  395.     valstext.FrontPen=col^(power(2,depth)-1);
  396.     valstext.BackPen=col;
  397.     PrintIText(PWindow->RPort,&valstext,115,45);
  398.     return(0);
  399. }
  400.  
  401. static power(base,n)
  402. int base,n;
  403. {
  404.     int p;
  405.     for (p=1;n>0;--n) p*=base;
  406.     return(p);
  407. }
  408.  
  409. static drawersquares(depth)
  410. int depth;
  411. {
  412.     int w,h,ox,x,y,i;
  413.     w=235/(power(2,depth)); h=25; ox=12;
  414.     if (depth==4) { w=29; h=12; ox=13; }
  415.     if (depth==5) { w=14; h=12; ox=17; }
  416.     i=0; x=ox; y=15;
  417.     while (x<255 && y<45) {
  418.         SetAPen(PWindow->RPort,i);
  419.         RectFill(PWindow->RPort,x,y,x+w,y+h);
  420.         ++i;
  421.         x+=w;
  422.         if (i>=power(2,depth)) break;
  423.         if (depth>3 && i==(power(2,(depth-1)))) {
  424.             x=ox; y+=h;
  425.         }
  426.     }
  427.     return(0);
  428. }
  429.  
  430. static dospread(first,last)
  431. int first,last;
  432. {
  433.     int redst,greenst,bluest,red1,green1,blue1,red2,green2,blue2,
  434.         redw,greenw,bluew,i;
  435.     colb=INITREG(first);
  436.     red1=REDREG(colb); green1=GREENREG(colb); blue1=BLUEREG(colb);
  437.     colb=INITREG(last);
  438.     red2=REDREG(colb); green2=GREENREG(colb); blue2=BLUEREG(colb);
  439.     redst=((red2-red1)<<8)/(last-first);
  440.     greenst=((green2-green1)<<8)/(last-first);
  441.     bluest=((blue2-blue1)<<8)/(last-first);
  442.     for (i=first+1;i<last;i++) {
  443.         redw=red1+(((redst*(i-first))+128)>>8);
  444.         greenw=green1+(((greenst*(i-first))+128)>>8);
  445.         bluew=blue1+(((bluest*(i-first))+128)>>8);
  446.         SetRGB4(cvp,i,redw,greenw,bluew);
  447.     }
  448.     return(0);
  449. }
  450.  
  451. /* HSL <-> RGB routines
  452.    adapted from the Amiga Programmers' Suite Book 1
  453.       by Robert J. Mical
  454.  
  455. ------------------------------------------------------------------------------
  456.  
  457.  * *** hsl.c ****************************************************************
  458.  *
  459.  * ColorWindow Routine    --  HSL Translation Routines
  460.  *     from Book 1 of the Amiga Programmers' Suite by RJ Mical
  461.  *
  462.  * Copyright (C) 1986, 1987, Robert J. Mical
  463.  * All Rights Reserved.
  464.  *
  465.  * Any or all of this code can be used in any program as long as this
  466.  * entire copyright notice is retained, ok?  Thanks.
  467.  *
  468.  * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
  469.  * All copyright notices and all file headers must be retained intact.
  470.  * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
  471.  * resultant object code may be included in any software product.  However, no
  472.  * portion of the source listings or documentation of the Amiga Programmer's
  473.  * Suite Book 1 may be distributed or sold for profit or in a for-profit
  474.  * product without the written authorization of the author, RJ Mical.
  475.  *
  476.  * HISTORY    NAME        DESCRIPTION
  477.  * -----------    --------------    --------------------------------------------
  478.  * 3 Jan 87    RJ >:-{)*    Clean-up for release
  479.  * 27 Feb 86    =RJ Mical=    Modified these routines for Zaphod
  480.  * January 86    =RJ=        Modified the originals for Mandelbrot
  481.  * Late 85    =RJ=        Created the color window for Graphicraft
  482.  *
  483.  * *************************************************************************
  484.  
  485. -----------------------------------------------------------------------------
  486.  
  487. */
  488.  
  489.  
  490. static HSLToRGB(hue,sat,lum)
  491. USHORT hue, sat, lum;
  492. {
  493.     ULONG red,green,blue,rdiff,gdiff,bdiff,foo,ris,fall,inv;
  494.  
  495.     foo=hue/0x2aab; ris=(hue-(foo*0x2aab))*6; fall=0xffff-ris;
  496.     red=0xffff; green=0xffff; blue=0xffff;
  497.     switch (foo) {
  498.         case 0:
  499.             green=ris; blue=0;
  500.             break;
  501.         case 1:
  502.             red=fall; blue=0;
  503.             break;
  504.         case 2:
  505.             red=0; blue=ris;
  506.             break;
  507.         case 3:
  508.             red=0; green=fall;
  509.             break;
  510.         case 4:
  511.             red=ris; green=0;
  512.             break;
  513.         case 5:
  514.             green=0; blue=fall;
  515.             break;
  516.     }
  517.  
  518.     red=(red*lum)>>16; green=(green*lum)>>16; blue=(blue*lum)>>16;
  519.     inv=0xffff-sat;
  520.     rdiff=lum-red; red=red+((rdiff*inv)>>16);
  521.     gdiff=lum-green; green=green+((gdiff*inv)>>16);
  522.     bdiff=lum-blue; blue=blue+((bdiff*inv)>>16);
  523.     red=(red>>12)&0xf; green=(green>>12)&0xf; blue=(blue>>12)&0xf;
  524.     return((SHORT)((red<<8)|(green<<4)|(blue)));
  525. }
  526.  
  527. static RGBToHSL(rgb,rhue,rsat,rlum)
  528. USHORT rgb;
  529. USHORT *rhue,*rsat,*rlum;
  530. {
  531.     LONG min,max,hue,sat,lum,diff,rpart,gpart,bpart,rwork,gwork,bwork;
  532.  
  533.     rwork=((rgb>>8)&0xf)*0x111; gwork=((rgb>>4)&0xf)*0x111; bwork=(rgb&0xf)*0x111;
  534.     if (rwork<gwork) min=rwork; else min=gwork; if (bwork<min) min=bwork;
  535.     if (rwork>gwork) max=rwork; else max=gwork; if (bwork>max) max=bwork;
  536.     lum=max; lum<<=4; diff=max-min;
  537.     if (max) {
  538.         sat=(diff<<16)/max; if (sat>0xffff) sat=0xffff;
  539.     }
  540.     else sat=0;
  541.     if (sat==0) hue=0;
  542.     else {
  543.         rpart=(((max-rwork)<<16)/diff)>>4;
  544.         gpart=(((max-gwork)<<16)/diff)>>4;
  545.         bpart=(((max-bwork)<<16)/diff)>>4;
  546.         if (rwork==max) hue=bpart-gpart;
  547.         else if (gwork==max) hue=0x2000+rpart-bpart;
  548.         else if (bwork==max) hue=0x4000+gpart-rpart;
  549.         if (hue<0) hue+=0x6000; hue=(hue*2667)/1000;
  550.     }
  551.     *rhue=hue; *rsat=sat; *rlum=lum;
  552.     return(0);
  553. }
  554.  
  555. /*--------------------------------------------------------------------------*/
  556.  
  557. dostr(val)
  558. int val;
  559. {
  560.     if (val<10) return(val+48);
  561.     return(val+87);
  562. }
  563.